#include "KedisConfig.h"
#include "KedisUtils.h"

unsigned long get_pid() {
    #ifdef _WIN32
        return static_cast<unsigned long>(GetCurrentProcessId());
    #else
        return static_cast<unsigned long>(getpid());
    #endif
}

// 工具函数：去除字符串首尾空白
std::string KedisConfig::trim(const std::string& str) {
    size_t first = str.find_first_not_of(" \t");
    if (first == std::string::npos) return "";
    size_t last = str.find_last_not_of(" \t");
    return str.substr(first, last - first + 1);
}

// 示例：多线程读写测试
void readConfig(KedisConfig& config, const std::string& key) {
    for (int i = 0; i < 5; ++i) {
        std::string value = config.get(key);
        std::cout << "Thread " << std::this_thread::get_id() << " read " << key << " = " << value << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }
}

void writeConfig(KedisConfig& config, const std::string& key, const std::string& value) {
    config.set(key, value);
    std::cout << "Thread " << std::this_thread::get_id() << " set " << key << " = " << value << std::endl;
    config.saveConfig(); // 保存到文件，触发监控线程检测
}

// Add this before the class definition or in a utility header
bool match_pattern(const std::string& pattern, const std::string& key) {
    if (pattern.empty()) return true; // No pattern matches all
    size_t p = 0, k = 0;
    while (p < pattern.size() && k < key.size()) {
        if (pattern[p] == '*') {
            // Skip the '*' and try matching the rest of the pattern
            p++;
            if (p == pattern.size()) return true; // '*' at end matches rest
            while (k < key.size()) {
                if (match_pattern(pattern.substr(p), key.substr(k))) return true;
                k++;
            }
            return false;
        } else if (pattern[p] == '?' || pattern[p] == key[k]) {
            p++;
            k++;
        } else {
            return false;
        }
    }
    return p == pattern.size() && k == key.size();
}

KedisConfig::KedisConfig(const std::string file_name) : running_(true), file_name_(file_name) 
{
    fs::path path = fs::path(AppDirectory::GetAppDirectory()) / file_name_;
    std::string filePath = path.string();

    if (std::filesystem::exists(filePath)) {
        last_modified_ = std::filesystem::last_write_time(filePath);
    }
    start();
}

KedisConfig::~KedisConfig() {
    running_ = false;
    if (monitor_thread_.joinable()) {
        monitor_thread_.join();
    }
}

bool KedisConfig::start() {
    if (!loadConfigInternal()) {
        return false;
    }
    monitor_thread_ = std::thread(&KedisConfig::monitorFile, this);
    return true;
}

std::string KedisConfig::get(const std::string& key, const std::string& default_value) const {
    std::shared_lock<std::shared_mutex> lock(mutex_); // 共享锁（读）
    auto it = config_map_.find(key);
    if (it != config_map_.end()) {
        return it->second;
    }
    return default_value;
}

void KedisConfig::parseLine(const std::string& line) {
    if (line.empty() || line[0] == '#') return;

    std::istringstream iss(line);
    std::string key, value;
    if (iss >> key) {
        std::getline(iss, value);
        value = trim(value);
        if (!value.empty()) {
            config_map_[trim(key)] = value;
        }
    }
}

bool KedisConfig::saveConfig() {
    std::unique_lock<std::shared_mutex> lock(mutex_); // 独占锁（写）
    std::ofstream file(file_name_);
    if (!file.is_open()) {
        std::cerr << "Failed to open file for writing: " << file_name_ << std::endl;
        return false;
    }

    for (const auto& pair : config_map_) {
        file << pair.first << " " << pair.second << "\n";
    }
    file.close();
    last_modified_ = std::filesystem::last_write_time(file_name_);
    return true;
}

void KedisConfig::set(const std::string& key, const std::string& value) {
    std::unique_lock<std::shared_mutex> lock(mutex_); // 独占锁（写）
    config_map_[key] = value;
}

bool KedisConfig::loadConfigInternal() {
    //std::string filePath = AppDirectory::GetAppDirectory() + "\\" + file_name_;
    fs::path path = fs::path(AppDirectory::GetAppDirectory()) / file_name_; // 自动使用正确的分隔符
    std::string filePath = path.string();
    std::cout << "path:" << filePath << "\n";
    std::ifstream file(filePath);
    if (!file.is_open()) {
        LOGE("Failed to open file: " << filePath);
        return false;
    }

    std::unordered_map<std::string, std::string> temp_map;
    std::string line;
    while (std::getline(file, line)) {
        std::istringstream iss(line);
        std::string key, value;
        if (iss >> key && !key.empty() && key[0] != '#') {
            std::getline(iss, value);
            value = trim(value);
            if (!value.empty()) {
                temp_map[trim(key)] = value;
            }
        }
    }
    file.close();

    // 更新 config_map_（使用独占锁）
    std::unique_lock<std::shared_mutex> lock(mutex_);
    config_map_ = std::move(temp_map);
    last_modified_ = std::filesystem::last_write_time(filePath);
    return true;
}

void KedisConfig::monitorFile() {
    fs::path path = fs::path(AppDirectory::GetAppDirectory()) / file_name_; // 自动使用正确的分隔符
    std::string filePath = path.string();
    while (running_) {
        auto current_modified = std::filesystem::last_write_time(filePath);
        if (current_modified != last_modified_) {
            LOG("Detected change in " << file_name_ << ", reloading config...");
            if (loadConfigInternal()) {
                LOG("Config reloaded successfully.");
            } else {
                LOG("Failed to reload config.");
            }
        }
        std::this_thread::sleep_for(std::chrono::seconds(60)); // 每30秒检查一次
    }
}